/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.area.field.shape;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import nl.cloudfarming.client.area.field.AreaFieldModule;
import nl.cloudfarming.client.geoviewer.LayerObject;
import nl.cloudfarming.client.geoviewer.LayerObjectAction;
import nl.cloudfarming.client.model.Bean;
import nl.cloudfarming.client.util.GeometryUtil;
import org.openide.util.NbBundle;

/**
 * non persistent object for storing geometries and additional information
 *
 *
 * @author Timon Veenstra
 */
public class Shape extends Bean implements LayerObject<Geometry, Shape>{

    private static long lastId = 0l;
    private Geometry geometry;
    private String name;
    private final long id;
    private ShapeType type;

    /**
     *
     */
    public Shape() {
        this.id = lastId++;
    }

    /**
     * Construct a shape object based on a WKT string
     *
     * @param wkt will be transformed into a Geometry
     * @throws ParseException
     */
    public Shape(String wkt) throws ParseException {       
        this.geometry = GeometryUtil.wktToGeometry(wkt);  
        this.id = lastId++;
    }

    /**
     * Create a shape object based on a Geometry
     *
     * @param geometry
     */
    public Shape(Geometry geometry) {
        this.geometry = geometry;
        this.id = lastId++;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        String old = this.name;
        this.name = name;
        getPropertyChangeSupport().firePropertyChange("name", old, name);
        fireUndoableEvent("name", this, old, name);
    }

    @Override
    public Geometry getGeometry() {
        return geometry;
    }

    @Override
    public long getId() {
        return id;
    }

    public ShapeType getType() {
        return type;
    }

    public void setType(ShapeType type) {
        ShapeType old = this.type;
        this.type = type;
        getPropertyChangeSupport().firePropertyChange("type", old, type);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Shape other = (Shape) obj;
        if (this.geometry != other.geometry && (this.geometry == null || !this.geometry.equals(other.geometry))) {
            return false;
        }
        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
            return false;
        }
        if (this.id != other.id) {
            return false;
        }
        if (this.type != other.type) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = super.hashCode();
        hash = 79 * hash + (this.geometry != null ? this.geometry.hashCode() : 0);
        hash = 79 * hash + (this.name != null ? this.name.hashCode() : 0);
        hash = 79 * hash + (int) (this.id ^ (this.id >>> 32));
        hash = 79 * hash + (this.type != null ? this.type.hashCode() : 0);
        return hash;
    }

    @Override
    public Shape getObject() {
        return this;
    }

    @Override
    public String getKey() {
        return getName();
    }

    @Override
    public Object getKeyAttributeValue() {
        return getName();
    }

    @Override
    public String getTooltipText() {
        return getName();
    }

    @Override
    public void save() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public LayerObjectAction[] getActions() {
        return null;
    }

    /**
     * Shape builder class
     *
     * usage: Shape shape = new Shape.Builder().setName("someName").build();
     *
     */
    public static class Builder{

        private Shape shape;
        
        public Builder() {
           shape = new Shape();
        }
        
        public Builder setName(String name){ 
           shape.setName(name);
           return this;
        }
        
        public Builder setType(ShapeType type){ 
           shape.setType(type);
           return this;
        }

        public Shape build() {
            return shape;
        }
    }
    
    /**
     * Type of a shape object
     * Gives an indication about what kind of shape it is, what the purpose is
     * and where it needs to be stored eventually.
     *
     * @author Timon Veenstra
     */
    public enum ShapeType {

        /**
         * Skip this shape
         */
        SKIP,
        /**
         * Field shape, Geometry will be a MultiPolygon
         */
        FIELD,
        /**
         * Field shape, Geometry will be a MultiPolygon
         */
//        FIELD,
        /**
         * ab-line shape, Geometry will be a line
         */
//        AB_LINE,
        /**
         * helpline shape, Geometry will be a line
         */
//        HELPLINE
                ;

        @Override
        public String toString() {
            return NbBundle.getMessage(AreaFieldModule.class, "shapetype."+name().toLowerCase());
        }


    }
}
